import datetime
import logging
import parsel
import os

from bs4 import BeautifulSoup
from django.conf import settings
from django.db.models import F
from django.views.decorators.http import require_http_methods

from forum.models import Topic, TopicFollow, Attachments, TopicThumb, TopicCategory
from user_app.models import AccountInfo, AccountFollow
from utils import query_utils
from utils import wx_method
from utils.common_utils import json_response, Pagination
from utils.decorators import json_check, check_login, get_token_info
from utils.oss_utils import RunOSS
from utils.query_utils import delete_topic_common
from utils.time_util import now

logger = logging.getLogger(__name__)
error_logger = logging.getLogger("error")


def get_topic_category(request):
    category_list = TopicCategory.objects.filter(enable=0)
    result_list = []
    for item in category_list:
        tmp = {
            "id": item.id, "category": item.category
        }
        result_list.append(tmp)
    return json_response({"code": 0, "message": "", "data": {"item": result_list}})


@check_login
@json_check
def post_topic(request, json_data):
    phone = request.session['phone']
    account = AccountInfo.objects.get(mobile_phone=phone)
    subject = json_data.get("subject")
    content = json_data.get("content")
    has_imgs = json_data.get("has_imgs")
    has_video = json_data.get("has_video")
    attachments_ids = json_data.get("attachments_ids")
    is_simple = json_data.get("is_simple", False)
    is_mobile = json_data.get("is_mobile", False)
    is_top = json_data.get("is_top", False)
    flag, msg = query_utils.check_allow_post(account.id)
    if flag:
        return json_response({"code": 1000, "message": msg})
    if is_mobile:
        # 小程序端需要文本内容合法性校验
        soup = BeautifulSoup(content, 'html.parser')
        parser_content = soup.get_text()
        code, message = wx_method.wx_check_content(parser_content)
        if code != 0:
            return json_response({"code": code, "message": message})
    new_topic = Topic()
    new_topic.subject = subject
    new_topic.content = content
    new_topic.account_info = account
    new_topic.has_imgs = has_imgs
    new_topic.has_video = has_video
    new_topic.is_simple = is_simple
    new_topic.last_post_account_id = None
    if has_imgs or has_video:
        new_topic.has_attachments = True
    if is_top:
        topic_level = Topic.objects.values('level').order_by('-level').first().get('level', 0)
        new_topic.level = topic_level + 1
    new_topic.save()
    new_topic.refresh_from_db()
    at = Attachments.objects.filter(id__in=attachments_ids, topic_id=0)
    if at:
        at.update(topic_id=new_topic.id, category=0)
    result_dict = {
        "topicid": new_topic.id
    }
    return json_response({"code": 0, "message": "发布成功", "data": result_dict})


@get_token_info
@json_check
def get_topic_detail(request, json_data):
    account_id = request.session.get('account_id', '')
    topic_id = int(json_data.get('topic_id'))
    topic = Topic.objects.get(id=topic_id)
    soup = BeautifulSoup(topic.content, 'html.parser')
    parser_content = soup.get_text()[:120]
    result_dict = {
        "id": topic.id,
        "subject": topic.subject,
        "content": topic.content,
        "numreplies": topic.num_replies,
        "numthumb": topic.num_thumb,
        "numviews": topic.num_views,
        "level": topic.level,
        "hidden": topic.hidden,
        "is_simple": topic.is_simple,
        "is_top": False if topic.level == 0 else True,
        "accountid": topic.account_info.id,
        "account": topic.account_info.nick_name,
        "accountisfollow": AccountFollow.objects.filter(created_by_id=account_id,
                                                        follow_account_id=topic.account_info.id).exists() if account_id else False,
        "avatar": topic.account_info.avatar,
        "time": topic.created_on,
        "isthumb": TopicThumb.objects.filter(topic_id=topic.id, created_by_id=account_id,
                                             category=0).exists() if account_id else False,
        "isfollow": TopicFollow.objects.filter(follow_topic_id=topic.id, created_by_id=account_id,
                                               category=0).exists() if account_id else False,
        "recentlytopic": __get_account_recently_topic(topic.account_info.id, topic_id),
        "parser_content": parser_content,
        "img_list": query_utils.get_img_attachments(topic.id, category=0),
        "vdo_list": query_utils.get_video_attachments(topic.id, category=0)
    }
    topic.num_views = F('num_views') + 1
    topic.save(update_fields=['num_views'])
    # topic.refresh_from_db()
    return json_response({"code": 0, "message": "", "data": result_dict})


@get_token_info
def get_topic_list(request):
    account_id = request.session.get('account_id', '')
    # 首页获取帖子
    page = int(request.GET.get('page', "1"))
    per_page = int(request.GET.get("per_page", "10"))
    topic_count = Topic.objects.filter(hidden=False).count()
    p = Pagination(page=page, per_page=per_page, total=topic_count)
    topic_list = Topic.objects.filter(hidden=False).order_by("-level", "-created_on")[p.offset:p.offset + per_page]
    result_list = []
    today = datetime.datetime.now()
    for item in topic_list:
        soup = BeautifulSoup(item.content, 'html.parser')
        parser_content = soup.get_text()[:80]

        tmp = {
            "id": item.id,
            "subject": item.subject,
            "content": parser_content,
            "numreplies": item.num_replies,
            "numthumb": item.num_thumb,
            "numviews": item.num_views,
            "level": item.level,
            "account": item.account_info.nick_name,
            "accountid": item.account_info.id,
            "avatar": item.account_info.avatar,
            # "lastpost": item.last_post_account_id.nick_name if item.last_post_account_id else "",
            # "lastreplyon": item.last_reply_on,
            "lastpost": "",
            "lastreplyon": item.created_on,
            "ishot": True if item.created_on.year == today.year and item.created_on.month == today.month and item.created_on.day == today.day else False,
            "img_list": query_utils.get_img_attachments(item.id, category=0),
            "vdo_list": query_utils.get_video_attachments(item.id, category=0),
            "accountisfollow": AccountFollow.objects.filter(created_by_id=account_id,
                                                            follow_account_id=item.account_info.id).exists() if account_id else False,
        }
        result_list.append(tmp)
    return json_response({"code": 0, "message": "", "data": {"item": result_list, "page_info": p.dict}})


def get_top10_topic(request):
    # 首页界面，不需要登录也能看
    tc = Topic.objects.raw(
        "SELECT id,subject,num_replies,num_thumb,num_views,account_info_id,last_post_account_id_id,last_reply_on, num_replies+num_views as total FROM `forum_topic` order by total desc;")[
         :10]
    p = Pagination(page=1, per_page=10, total=10)
    result_list = []
    for item in tc:
        tmp = {
            "id": item.id,
            "subject": item.subject,
            # "content": parser_content,
            "numreplies": item.num_replies,
            "num_thumb": item.num_thumb,
            "num_views": item.num_views,
            "account": item.account_info.nick_name,
            "lastpost": item.last_post_account_id.nick_name if item.last_post_account_id else "",
            "lastreplyon": item.last_reply_on,
            "avatar": item.account_info.avatar
        }
        result_list.append(tmp)
    return json_response({"code": 0, "message": "", "data": {"item": result_list, "page_info": p.dict}})


@check_login
def topic_thumb(request):
    # 给帖子点赞/取消赞接口
    account_id = request.session['account_id']
    topic_id = request.GET.get('topic_id')
    flag, tc = __check_topic(topic_id)
    if not flag:
        return json_response({"code": 1000, "message": "帖子不存在"})
    thumb = TopicThumb.objects.filter(created_by_id=account_id, topic_id=topic_id, category=0)
    result_dict = {

    }
    if thumb:
        thumb.delete()
        result_dict['flag'] = False
        topic = tc[0]
        topic.num_thumb = F('num_thumb') - 1
        topic.save(update_fields=['num_thumb'])
        return json_response({"code": 0, "message": "取消点赞", "data": result_dict})
    else:
        tb = TopicThumb()
        tb.topic_id = topic_id
        tb.topic_account_id = tc[0].account_info.id
        tb.created_by_id = account_id
        tb.save()
        result_dict['flag'] = True
        topic = tc[0]
        topic.num_thumb = F('num_thumb') + 1
        topic.save(update_fields=['num_thumb'])
        return json_response({"code": 0, "message": "点赞成功", "data": result_dict})


@check_login
def topic_follow(request):
    # 帖子收藏接口
    account_id = request.session['account_id']
    topic_id = request.GET.get('topic_id')
    flag, tc = __check_topic(topic_id)
    if not flag:
        return json_response({"code": 1000, "message": "帖子不存在"})
    if account_id == tc[0].account_info.id:
        return json_response({"code": 1000, "message": "无法收藏自己的帖子"})
    follow = TopicFollow.objects.filter(created_by_id=account_id, follow_topic_id=topic_id, category=0)
    result_dict = {

    }
    if follow:
        follow.delete()
        result_dict['flag'] = False
        return json_response({"code": 0, "message": "取消收藏", "data": result_dict})
    else:
        fw = TopicFollow()
        fw.follow_topic_id = topic_id
        fw.topic_account_id = tc[0].account_info.id
        fw.created_by_id = account_id
        fw.save()
        result_dict['flag'] = True
        return json_response({"code": 0, "message": "收藏成功", "data": result_dict})


@check_login
def search_topic(request):
    keyword = request.GET.get('keyword')
    page = int(request.GET.get('page', "1"))
    per_page = int(request.GET.get("per_page", "10"))
    topic_count = Topic.objects.filter(subject__contains=keyword, hidden=False).count()
    p = Pagination(page=page, per_page=per_page, total=topic_count)
    topic_list = Topic.objects.filter(subject__contains=keyword, hidden=False).order_by("-created_on")[p.offset:p.offset + per_page]
    result_list = []
    for item in topic_list:
        soup = BeautifulSoup(item.content, 'html.parser')
        parser_content = soup.get_text()
        tmp = {
            "id": item.id,
            "subject": item.subject,
            "content": parser_content,
            "numreplies": item.num_replies,
            "numthumb": item.num_thumb,
            "numviews": item.num_views,
            "account": item.account_info.nick_name,
            "avatar": item.account_info.avatar,
            # "lastpost": item.last_post_account_id.nick_name if item.last_post_account_id else "",
            "lastpost": "",
            "lastreplyon": item.last_reply_on,
            "img_list": query_utils.get_img_attachments(item.id, category=0)
        }
        result_list.append(tmp)
    return json_response({"code": 0, "message": "", "data": {"item": result_list, "page_info": p.dict}})


@check_login
def delete_topic(request):
    account_id = request.session['account_id']
    topic_id = request.GET.get('topic_id')
    # if not Topic.objects.filter(id=topic_id).exists():
    #     return json_response({"code": 1000, "message": "帖子不存在"})
    if not Topic.objects.filter(id=topic_id, account_info=account_id).exists():
        return json_response({"code": 1000, "message": "权限不足或帖子不存在"})
    flag = delete_topic_common(topic_id)
    if not flag:
        return json_response({"code": 1000, "message": "删除失败，请稍后再试"})
    return json_response({"code": 0, "message": "删除成功"})


@check_login
def attachments_upload_norecord(request):
    # 附件上传接口，不记录到DB
    try:
        file = request.FILES['file']
        filename = file.name
        oss = RunOSS(filename=filename, dirname=settings.OSS_UPLOAD_VOUCHER_DIR)
        ret = oss.uploadFIle(objectfile=file)
        status = ret.get("status")
        if status == 200:
            file_url = ret['pay_certificate']
            result_dict = {
                "fileurl": file_url,
                "filename": filename
            }
            return json_response({"code": 0, "message": "上传成功", "data": result_dict})
        else:
            return json_response({"code": 1000, "message": "OSS传输失败"})
    except Exception as e:
        error_logger.exception("attachments_upload_norecord have a  error ---->%s" % e.__str__())
        return json_response({"code": 4000, "message": "服务器内部错误"})


@check_login
def attachments_upload(request):
    # 附件上传接口
    try:
        account_id = request.session['account_id']
        file = request.FILES['file']
        filename = file.name
        oss = RunOSS(filename=filename, dirname=settings.OSS_UPLOAD_VOUCHER_DIR)
        ret = oss.uploadFIle(objectfile=file)
        # ret = {'status': 200, 'pay_certificate': 'http://u3dmodels.oss-cn-beijing.aliyuncs.com/voucher/202103041020485502.jpg', 'objectname': 'voucher/202103041020485502.jpg'}
        status = ret.get("status")
        if status == 200:
            file_url = ret['pay_certificate']
            new_acm = Attachments()
            new_acm.file_url = file_url
            new_acm.file_name = filename
            new_acm.suffix = filename.split(".")[-1]
            new_acm.topic_id = 0
            new_acm.created_by_id = account_id
            new_acm.save()
            new_acm.refresh_from_db()
            result_dict = {
                "fileid": new_acm.id,
                "fileurl": file_url,
                "filename": filename
            }
            return json_response({"code": 0, "message": "上传成功", "data": result_dict})
        else:
            return json_response({"code": 1000, "message": "OSS传输失败"})
    except Exception as e:
        error_logger.exception("attachments_upload have a  error ---->%s" % e.__str__())
        return json_response({"code": 4000, "message": "服务器内部错误"})


@require_http_methods(['POST'])
@check_login
@json_check
def update_topic(request, json_data):
    """
        帖子编辑接口
    """
    phone = request.session['phone']
    account = AccountInfo.objects.get(mobile_phone=phone)

    topicid = json_data.get("topicid")
    subject = json_data.get("subject")
    content = json_data.get("content")
    has_imgs = json_data.get("has_imgs")
    has_video = json_data.get("has_video")
    #img_list = json_data.get("img_list")
    is_simple = json_data.get("is_simple", False)
    is_mobile = json_data.get("is_mobile", False)

    if is_mobile:
        # 小程序端需要文本内容合法性校验
        soup = BeautifulSoup(content, 'html.parser')
        parser_content = soup.get_text()
        code, message = wx_method.wx_check_content(parser_content)
        if code != 0:
            return json_response({"code": code, "message": message})
    attachments_ids = []
    current_topic = Topic.objects.get(id=topicid)
    # 先清除旧附件的绑定关系
    Attachments.objects.filter(topic_id=current_topic.id).update(topic_id=0)
    # 这里会把快捷发帖转换成普通发帖，只需要读取content里面的img,video标签，获取OSS路径即可
    selector = parsel.Selector(content)
    images = selector.css('img::attr(src)').getall()
    videos = selector.css('video::attr(src)').getall()
    for attach in images + videos:
        if attach.find("u3dmodels.oss-cn-beijing.aliyuncs.com/voucher") > -1:
            db_at = Attachments.objects.filter(file_url=attach)
            if db_at:
                attachments_ids.append(db_at[0].id)
            else:
                # 附件表中不存在的OSS路径，就insert新数据记录OSS文件
                filename = os.path.split(attach)
                new_acm = Attachments()
                new_acm.file_url = attach
                new_acm.file_name = filename[1]
                new_acm.suffix = filename[1].split(".")[-1]
                new_acm.topic_id = current_topic.id
                new_acm.created_by_id = account.id
                new_acm.save()
                new_acm.refresh_from_db()
                attachments_ids.append(new_acm.id)

    current_topic.subject = subject
    current_topic.content = content
    current_topic.account_info = account
    current_topic.has_imgs = has_imgs
    current_topic.has_video = has_video
    current_topic.is_simple = is_simple
    #current_topic.last_post_account_id = None
    current_topic.updated_on = now()
    if has_imgs or has_video:
        current_topic.has_attachments = True
    current_topic.save()
    # new_topic.refresh_from_db()
    Attachments.objects.filter(id__in=attachments_ids).update(topic_id=current_topic.id, category=0)
    result_dict = {
        "topicid": current_topic.id
    }
    return json_response({"code": 0, "message": "编辑成功", "data": result_dict})


@require_http_methods(['POST'])
@check_login
@json_check
def mobile_update_topic(request, json_data):
    """
        帖子编辑接口
    """
    phone = request.session['phone']
    account = AccountInfo.objects.get(mobile_phone=phone)

    topicid = json_data.get("topicid")
    subject = json_data.get("subject")
    content = json_data.get("content")
    has_imgs = json_data.get("has_imgs")
    has_video = json_data.get("has_video")
    attch_list = json_data.get("attch_list")
    is_simple = json_data.get("is_simple", False)
    is_mobile = json_data.get("is_mobile", False)
    is_top = json_data.get("is_top")
    if is_top is None:
        return json_response({"code": 1000, "message": "is_top参数丢失"})
    if is_mobile:
        # 小程序端需要文本内容合法性校验
        soup = BeautifulSoup(content, 'html.parser')
        parser_content = soup.get_text()
        code, message = wx_method.wx_check_content(parser_content)
        if code != 0:
            return json_response({"code": code, "message": message})
    current_topic = Topic.objects.get(id=topicid)
    # 先查询旧的绑定关系
    old_url_list = list(Attachments.objects.filter(topic_id=current_topic.id, category=0).values_list("file_url", flat=True))
    # 新增的附件
    new_attch = list(set(attch_list).difference(set(old_url_list)))
    # 需要清除的附件
    clear_attch = list(set(old_url_list).difference(set(attch_list)))
    Attachments.objects.filter(file_url__in=clear_attch, category=0).exclude(topic_id=0).update(topic_id=0)

    current_topic.subject = subject
    current_topic.content = content
    current_topic.account_info = account
    current_topic.has_imgs = has_imgs
    current_topic.has_video = has_video
    current_topic.is_simple = is_simple
    #current_topic.last_post_account_id = None
    current_topic.updated_on = now()
    if is_top:
        current_level = Topic.objects.values('level').order_by('-level').first().get('level', 0)
        current_topic.level = current_level + 1
    else:
        current_topic.level = 0
    if has_imgs or has_video:
        current_topic.has_attachments = True
    current_topic.save()
    # new_topic.refresh_from_db()
    Attachments.objects.filter(file_url__in=new_attch).update(topic_id=current_topic.id, category=0)
    result_dict = {
        "topicid": current_topic.id
    }
    return json_response({"code": 0, "message": "编辑成功", "data": result_dict})


def __get_account_recently_topic(account_id, topic_id):
    # 获取某个用户最近的6条帖子
    result_list = []
    tc = Topic.objects.filter(account_info=account_id).exclude(id=topic_id).order_by("-created_on")[:6]
    for item in tc:
        tmp = {
            "id": item.id,
            "subject": item.subject,
            # "content": item.content,
            "numreplies": item.num_replies,
            "numthumb": item.num_thumb,
            "numviews": item.num_views,
            "account": item.account_info.nick_name,
            "time": item.created_on,
        }
        result_list.append(tmp)
    return result_list


def __check_topic(topic_id):
    tc = Topic.objects.filter(id=topic_id)
    if not tc:
        return False, tc
    return True, tc
